"""
可变对象和不可变对象在理解python的深拷贝和浅拷贝有帮助

可变对象
可变对象是指那些在创建后可以被修改的对象。常见的可变对象包括：

- 列表 (list)
- 字典 (dict)
- 集合 (set)
- 自定义类的实例（如果该类允许修改其属性）

不可变对象
不可变对象是指那些在创建后不能被修改的对象。常见的不可变对象包括：

- 数字（整数 int、浮点数 float、复数 complex）
- 字符串 (str)
- 元组 (tuple)
- 冻结集合 (frozenset)
- 布尔值 (bool)

示例
- 查看参数传递

"""
# 1. 创建一个可变对象实例
# 创建一个包含可变对象的列表
mutable_list = [1, 2, [3, 4], 5]

# 修改列表中的可变对象
mutable_list[2].append(6)
print(mutable_list)  # 输出: [1, 2, [3, 4, 6], 5]

# 2. 创建一个不可变对象实例
# 创建一个包含不可变对象的列表
immutable_list = [1, 2, (3, 4), 5]

# 尝试修改列表中的不可变对象
try:
    immutable_list[2][0] = 30
except TypeError as e:
    print(e)  # 输出: 'tuple' object does not support item assignment

# 3. 混合使用
mixed_list = [1, 2, [3, 4], (5, 6), {'key': 'value'}, {7, 8}]

# 修改可变对象
mixed_list[2].append(5)  # 修改嵌套列表
mixed_list[4]['key'] = 'new_value'  # 修改字典
mixed_list[5].add(9)  # 修改集合

print(mixed_list)  # 输出: [1, 2, [3, 4, 5], (5, 6), {'key': 'new_value'}, {8, 9, 7}]


# 示例 参数传递

# 参数传递示例1
# immutable objects -> no change
def foo(x):
    x = 5  # x += 5 also no effect since x is immutable and a new variable must be created


var = 10
print('var before foo():', var)  # 10
foo(var)
print('var after foo():', var)  # 10


# 参数传递示例2
# mutable objects -> change
def foo(a_list):
    a_list.append(4)


my_list = [1, 2, 3]
print('my_list before foo():', my_list)  # [1, 2, 3]
foo(my_list)
print('my_list after foo():', my_list)  # [1, 2, 3, 4]


# 参数传递示例3
# immutable objects within a mutable object -> change
def foo(a_list):
    a_list[0] = -100
    a_list[2] = "Paul"


my_list = [1, 2, "Max"]
print('my_list before foo():', my_list)  # [1, 2, "Max"]
foo(my_list)
print('my_list after foo():', my_list)  # [-100, 2, "Paul"]


# 参数传递示例4
# Rebind a mutable reference -> no change  重新绑定一个可变参数的应用,不会有变化
def foo(a_list):
    a_list = [50, 60, 70]  # a_list is now a new local variable within the function
    a_list.append(50)


my_list = [1, 2, 3]
print('my_list before foo():', my_list)  # [1, 2, 3]
foo(my_list)
print('my_list after foo():', my_list)  # [1, 2, 3]


# 参数传递示例5
# 其它示例：another example with rebinding references:
def foo(a_list):
    a_list += [4, 5]  # this chanches the outer variable


def bar(a_list):
    a_list = a_list + [4, 5]  # this rebinds the reference to a new local variable


my_list = [1, 2, 3]
print('my_list before foo():', my_list)  # [1, 2, 3]
foo(my_list)
print('my_list after foo():', my_list)  # [1, 2, 3,4,5]

my_list = [1, 2, 3]
print('my_list before bar():', my_list)  # [1, 2, 3]
bar(my_list)
print('my_list after bar():', my_list)  # [1, 2, 3]
